#ifndef UTL_H
#define UTL_H

#include <stdio.h>
#include <errno.h>

#define UTL_DEG2RAD (F_PI / 180.0f)
#define UTL_MIN(A,B) ((A)>(B)?(B):(A))
#define UTL_MAX(A,B) ((A)>(B)?(A):(B))
#define UTL_WHITESPACE "\r\t\n "
#define UTL_CRLF       "\r\n"

#if defined(_WIN32)
  #define data_dir "romdisk/data"
  #define SEED_RANDOM srand(GetTickCount())
  #define RANDOM_NUMBER (double)rand() / ((double)32768)
  #define GET_TIME_SECONDS (GetTickCount()/1000)
  #define UTL_ATAN2(dx,dy) atan2((dy),(dx))*(180/F_PI)
  #define timer_ms_gettime(a,b) \
  {                             \
    int tc = GetTickCount();    \
    *(a) = tc/1000;             \
    *(b) = tc%1000;             \
  }
  typedef char bool;
  typedef unsigned int uint32;
  typedef unsigned short uint16;
  typedef unsigned char uint8;
  typedef int int32;
  typedef short int16;
  typedef char int8;
#else
  #include <dc/g2bus.h>
  #if defined(USE_ROMDISK)
    #define data_dir "/rd/data"
  #else
    #define data_dir "/cd/gpwt/data"
  #endif
  #define SEED_RANDOM srand(g2_read_32(0xa0710004))
  #define RANDOM_NUMBER (double)rand() / ((double)0x7fffffff + 1)
  #define GET_TIME_SECONDS (g2_read_32(0xa0710004) & 0xffff)
  #define UTL_ATAN2(dx,dy) atan2((dy),(dx))*(180/F_PI)
  #define check_win32() 1
  #define strerror(n) "strerror not supported"
#endif

#define UTL_FIRE_PALETTE_SIZE      256
#define UTL_EXPLOSION_PALETTE_SIZE 256
#define UTL_RAINBOW_PALETTE_SIZE   16

#ifdef UTL_C
uint32 utl_explosion_palette[UTL_EXPLOSION_PALETTE_SIZE] =
{0xFEFEF4, 0xFEFDEB, 0xFEFEE2, 0xFEFDDB, 0xFEFDD4, 0xFEFCCC, 0xFEFCC3, 0xFDFCBB, 
 0xFEFCB1, 0xFEFBAB, 0xFEFBA4, 0xFEFB9B, 0xFEFA93, 0xFEF98C, 0xFFF593, 0xFEF884, 
 0xFDFA75, 0xFEF58B, 0xFDF87D, 0xFEF582, 0xFEF679, 0xFCF96C, 0xFEF674, 0xFAF867, 
 0xFDF469, 0xFDF364, 0xFFEE71, 0xFBF05D, 0xFEEC69, 0xFAF154, 0xF6F15A, 0xFDEB61, 
 0xF6F054, 0xFAED59, 0xF9F04B, 0xFAEB54, 0xF9EB4D, 0xF6ED4A, 0xF4EC52, 0xFCE652, 
 0xF8E946, 0xF5EA44, 0xF6E649, 0xF4E83E, 0xFAE343, 0xF9E24A, 0xF5E444, 0xEEE247, 
 0xF3E13D, 0xF7DD41, 0xEEE23E, 0xF1E136, 0xF1DA39, 0xEBDD38, 0xEED834, 0xEBDA2D, 
 0xECD431, 0xE6D432, 0xF1D029, 0xEBD22D, 0xF1CE2A, 0xE7D326, 0xF0CB34, 0xE6D129, 
 0xECCA33, 0xE6CD31, 0xEACB2C, 0xEBC925, 0xE5CA2A, 0xE9C62C, 0xECC331, 0xEAC424, 
 0xE6C429, 0xE4C126, 0xDEC327, 0xEABB25, 0xE2BE1F, 0xE3BA2B, 0xE2BB24, 0xE9B723, 
 0xDEBB1D, 0xE1B428, 0xE3B422, 0xDDB421, 0xE2B11E, 0xDCB31E, 0xD6B118, 0xE1AB19, 
 0xDAAD1D, 0xDBAB23, 0xD3AC21, 0xDBA521, 0xD5A91A, 0xD3AA14, 0xD9A41D, 0xDFA30F, 
 0xDBA315, 0xD6A322, 0xE19E19, 0xD6A31C, 0xDB9D18, 0xCEA118, 0xDB9A16, 0xD39D19, 
 0xCC9D18, 0xDA9614, 0xD29915, 0xCB9A15, 0xD09619, 0xD59608, 0xD59112, 0xCC941A, 
 0xCD9313, 0xC79512, 0xD38D12, 0xD28E0D, 0xC8910D, 0xCB8D12, 0xCB8A0B, 0xC48A1D, 
 0xC68910, 0xC48A0D, 0xCA8410, 0xCA840C, 0xC68510, 0xC5830E, 0xC1821B, 0xC68007, 
 0xBE820C, 0xBE8013, 0xC87C0C, 0xBC7C19, 0xC1780D, 0xBC7B11, 0xBD780B, 0xC17A04, 
 0xC37614, 0xC2750D, 0xBB7A02, 0xBA7412, 0xB77804, 0xBC730A, 0xC16F0C, 0xBC7300, 
 0xB77112, 0xB4730A, 0xB37302, 0xB96D09, 0xB86912, 0xBA6B01, 0xB66B09, 0xBA6509, 
 0xB56805, 0xAF6A08, 0xB96403, 0xAD6906, 0xB26409, 0xB36305, 0xAD6209, 0xB05F0E, 
 0xAE6105, 0xB25C01, 0xAC5D08, 0xAC5C03, 0xA9570B, 0xA45902, 0xA95500, 0xA25408, 
 0xA45301, 0xA84F00, 0x9D5106, 0x9B5008, 0xA04D02, 0x9A4B09, 0x9C4A04, 0x95490A, 
 0x974806, 0x984603, 0x924609, 0x924303, 0x8B4109, 0x8E4002, 0x933D00, 0x893D08, 
 0x8B3C01, 0x833C08, 0x843A01, 0x893509, 0x7F380A, 0x7C3902, 0x813602, 0x833208, 
 0x7A3408, 0x7B3302, 0x733209, 0x763102, 0x812A00, 0x742F08, 0x7B2C00, 0x6E300A, 
 0x6D3100, 0x722D02, 0x792600, 0x6B2B09, 0x6C2901, 0x732500, 0x682709, 0x642905, 
 0x692501, 0x5F2608, 0x642308, 0x632401, 0x5B2800, 0x631E04, 0x5C2201, 0x542300, 
 0x581E02, 0x531D04, 0x4D2003, 0x531908, 0x4D1A08, 0x511709, 0x4A1903, 0x501602, 
 0x481608, 0x451900, 0x4A1402, 0x3D1805, 0x43140A, 0x431504, 0x3E1008, 0x3B1102, 
 0x331108, 0x341102, 0x390D09, 0x3A0C04, 0x2E1008, 0x340808, 0x320C04, 0x390706, 
 0x350607, 0x340608, 0x2B0A05, 0x2B0908, 0x240904, 0x2A0504, 0x220808, 0x230604, 
 0x230508, 0x1A0804, 0x170803, 0x1B0403, 0x130303, 0x0B0001, 0x010000, 0x000000};
uint32 utl_fire_palette[UTL_FIRE_PALETTE_SIZE] = 
{0xFFFFFF, 0xFFFFFD, 0xFFFFFC, 0xFFFFFA, 0xFFFFF9, 0xFFFFF8, 0xFFFFF6, 0xFFFFF5, 
 0xFFFFF4, 0xFFFFF2, 0xFFFFF1, 0xFFFFF0, 0xFFFFEE, 0xFFFFED, 0xFFFFEC, 0xFFFFEA, 
 0xFFFFE9, 0xFFFFE8, 0xFFFFE6, 0xFFFFE5, 0xFFFFE4, 0xFFFFE2, 0xFFFFE1, 0xFFFFE0, 
 0xFFFFDE, 0xFFFFDD, 0xFFFFDC, 0xFFFFDA, 0xFFFFD9, 0xFFFFD8, 0xFFFFD6, 0xFFFFD5, 
 0xFFFFD4, 0xFFFFD2, 0xFFFFD1, 0xFFFFD0, 0xFFFFCE, 0xFFFFCD, 0xFFFFCC, 0xFFFFCA, 
 0xFFFFC9, 0xFFFFC8, 0xFFFFC6, 0xFFFFC5, 0xFFFFC4, 0xFFFFC2, 0xFFFFC1, 0xFFFFC0, 
 0xFFFFBE, 0xFFFFBD, 0xFFFFBC, 0xFFFFBA, 0xFFFFB9, 0xFFFFB8, 0xFFFFB6, 0xFFFFB5, 
 0xFFFFB4, 0xFFFFB2, 0xFFFFB1, 0xFFFFB0, 0xFFFFAE, 0xFFFFAD, 0xFFFFAC, 0xFFFFAA, 
 0xFFFFA9, 0xFFFFA8, 0xFFFFA6, 0xFFFFA5, 0xFFFFA4, 0xFFFFA2, 0xFFFFA1, 0xFFFFA0, 
 0xFFFF9E, 0xFFFF9D, 0xFFFF9C, 0xFFFF9A, 0xFFFF99, 0xFFFF98, 0xFFFF96, 0xFFFF95, 
 0xFFFF94, 0xFFFF92, 0xFFFF91, 0xFFFF90, 0xFFFF8E, 0xFFFF8D, 0xFFFF8C, 0xFFFF8A, 
 0xFFFF89, 0xFFFF88, 0xFFFF86, 0xFFFF85, 0xFFFF84, 0xFFFF82, 0xFFFF81, 0xFFFF80, 
 0xFFFF7E, 0xFFFF7D, 0xFFFF7C, 0xFFFF7A, 0xFFFF79, 0xFFFF78, 0xFFFF76, 0xFFFF75, 
 0xFFFF74, 0xFFFF72, 0xFFFF71, 0xFFFF70, 0xFFFF6E, 0xFFFF6D, 0xFFFF6C, 0xFFFF6A, 
 0xFFFF69, 0xFFFF68, 0xFFFF66, 0xFFFF65, 0xFFFF64, 0xFFFF62, 0xFFFF61, 0xFFFF60, 
 0xFFFF5E, 0xFFFF5D, 0xFFFF5C, 0xFFFF5A, 0xFFFF59, 0xFFFF58, 0xFFFF56, 0xFFFF55, 
 0xFFFF54, 0xFFFF52, 0xFFFF51, 0xFFFF50, 0xFFFF4E, 0xFFFF4D, 0xFFFF4C, 0xFFFF4A, 
 0xFFFF49, 0xFFFF48, 0xFFFF46, 0xFFFF45, 0xFFFF44, 0xFFFF42, 0xFFFF41, 0xFFFF40, 
 0xFFFF3E, 0xFFFF3D, 0xFFFF3C, 0xFFFF3A, 0xFFFF39, 0xFFFF38, 0xFFFF36, 0xFFFF35, 
 0xFFFF34, 0xFFFF32, 0xFFFF31, 0xFFFF30, 0xFFFF2E, 0xFFFF2D, 0xFFFF2C, 0xFFFF2A, 
 0xFFFF29, 0xFFFF28, 0xFFFF26, 0xFFFF25, 0xFFFF24, 0xFFFF22, 0xFFFF21, 0xFFFF20, 
 0xFFFF1E, 0xFFFF1D, 0xFFFF1C, 0xFFFF1A, 0xFFFF19, 0xFFFF18, 0xFFFF16, 0xFFFF15, 
 0xFFFF14, 0xFFFF12, 0xFFFF11, 0xFFFF10, 0xFFFF0E, 0xFFFF0D, 0xFFFF0C, 0xFFFF0A, 
 0xFFFF09, 0xFFFF08, 0xFFFF06, 0xFFFF05, 0xFFFF04, 0xFFFF02, 0xFFFF01, 0xFFFF00, 
 0xFFF700, 0xFFEF00, 0xFFE700, 0xFFDF00, 0xFFD700, 0xFFCF00, 0xFFC700, 0xFFBF00, 
 0xFFB700, 0xFFAF00, 0xFFA700, 0xFF9F00, 0xFF9700, 0xFF8F00, 0xFF8700, 0xFF8000, 
 0xF77804, 0xEF7008, 0xE7680C, 0xDF6010, 0xD75814, 0xCF5018, 0xC7481C, 0xBF4020, 
 0xB73824, 0xAF3028, 0xA7282C, 0x9F2030, 0x971834, 0x8F1038, 0x87083C, 0x800040, 
 0x780044, 0x700048, 0x68004C, 0x600050, 0x580054, 0x500058, 0x48005C, 0x400060, 
 0x380064, 0x300068, 0x28006C, 0x200070, 0x180074, 0x100078, 0x08007C, 0x000080, 
 0x000078, 0x000070, 0x000068, 0x000060, 0x000058, 0x000050, 0x000048, 0x000040, 
 0x000038, 0x000030, 0x000028, 0x000020, 0x000018, 0x000010, 0x000008, 0x000000};
uint32 utl_rainbow_palette[UTL_RAINBOW_PALETTE_SIZE] =
{0xFF0000, 0xFF8A01, 0xFFAE01, 0xFFFC01, 0x67FF01, 0x01FF0D, 0x01FFAE, 0x01FFFC, 
 0x0196FF, 0x0149FF, 0x1301FF, 0x6D01FF, 0xC601FF, 0xFF01F0, 0xFF01A2, 0xFF015B};
#else
extern uint32 utl_explosion_palette[UTL_EXPLOSION_PALETTE_SIZE];
extern uint32 utl_fire_palette[UTL_FIRE_PALETTE_SIZE];
extern uint32 utl_rainbow_palette[UTL_RAINBOW_PALETTE_SIZE];
#endif

#if defined(DEBUG_LEVEL)

#define DBG_FLUSH_DEF 1

#ifdef UTL_C
int dbg_lv = DEBUG_LEVEL;
int dbg_ln = 0;
int dbg_fl = DBG_FLUSH_DEF;
int dbg_watchit = 99;
#else
extern int dbg_lv;
extern int dbg_ln;
extern int dbg_fl;
extern int dbg_watchit;
#endif

#if defined(_WIN32)
#define DBG_BREAK DebugBreak()
#else
#define DBG_BREAK
#endif

#if 1
#define DBG_ENTRY(n,x) if ((n)<=dbg_lv) { printf(">> ");                 \
                                          printf x;                      \
                                          printf(" [%s:%d]\n",__FILE__   \
                                                            ,__LINE__);  \
                                          if (!(dbg_ln++%dbg_fl))        \
                                            fflush(stdout);}
#else
#define DBG_ENTRY(n,x)
#endif
                                               
#if 1
#define DBG_EXIT(n,x)  if ((n)<=dbg_lv) { printf("<< ");                 \
                                          printf x;                      \
                                          printf(" [%s:%d]\n",__FILE__   \
                                                            ,__LINE__);  \
                                          if (!(dbg_ln++%dbg_fl))        \
                                            fflush(stdout);}
#else
#define DBG_EXIT(n,x)
#endif

#if 1
#define DBG_PRINT(n,x) if ((n)<=dbg_lv) { printf("   ");                 \
                                          printf x;                      \
                                          printf(" [%s:%d]\n",__FILE__   \
                                                             ,__LINE__); \
                                          if (!(dbg_ln++%dbg_fl))        \
                                            fflush(stdout);}
#else                                                 
#define DBG_PRINT(n,x)
#endif

#if 1
#define DBG_ELSE(n,x) else { DBG_PRINT(n,x); }
#else
#define DBG_ELSE(n,x)
#endif

#if 1
#define DBG_IF(n,c,x) if c { DBG_PRINT(n,x); }
#else
#define DBG_IF(n,c,x)
#endif
 
#define DBG_INT(a,v) int a=v
#define DBG_INC(a) a++;
#define DBG_DEC(a) a--;

#define DBG_SET_FLUSH(n) dbg_flush=(n)
#define DBG_DEF_FLUSH    dbg_flush=DBG_FLUSH_DEF
#define DBG_SET_LEVEL(n) dbg_lv=(n)

#define DBG_MASK(n,i,w,h) if ((n)<=dbg_lv) { int y,x;                    \
                                             uint8 *p = (i);             \
                                             printf("\n");               \
                                             for(y=0; y<(h); y++)        \
                                             {                           \
                                               printf("|");              \
                                               for(x=0; x<(w); x++)      \
                                               {                         \
                                                 if (*p)                 \
                                                   printf("*");          \
                                                 else                    \
                                                   printf(" ");          \
                                                 p++;                    \
                                               }                         \
                                               printf("|\n");            \
                                             }                           \
                                             if (!(dbg_ln++%dbg_fl))     \
                                               fflush(stdout);           \
                                           }
#define DBG_MALLOC_STATS(n) if ((n)<=dbg_lv) malloc_stats();
#else
#define DBG_BREAK
#define DBG_ENTRY(n,x)
#define DBG_EXIT(n,x)
#define DBG_PRINT(n,x)
#define DBG_ELSE(n,x)
#define DBG_IF(n,c,x)
#define DBG_INT(a,v)
#define DBG_INC(a)
#define DBG_DEC(a)
#define DBG_SET_FLUSH(n)
#define DBG_DEF_FLUSH
#define DBG_SET_LEVEL(n)
#define DBG_MASK(n,i,w,h)
#define DBG_MALLOC_STATS(n)
#endif

/* FUNCTIONS */

#define utl_malloc malloc
#define utl_realloc realloc
#define utl_free free
                                             
#endif
